#ifndef PACMAN_H_
#define PACMAN_H_

#include "Posicionable.h"
#include "MapaDeCeldas.h"
#include <SDL_mixer.h>


class Pacman : public Posicionable{

private:

	int puntajeObtenido;
	int multiplicadorPuntaje;
	bool enMovimiento;
	int vidas;
	bool perseguido; // indica si el Pacman es perseguido(true) o es perseguidor(false)
	bool sumaPuntosRival;
	int siguienteDireccion;
	int velocidad;

public:

	static const int DIRARRIBA = 3;
	static const int DIRABAJO = 1;
	static const int DIRDERECHA = 0;
	static const int DIRIZQUIERDA = 2;
	static const int VIDASDEFAULT = 3;

	Pacman():Posicionable(){
		this->enMovimiento=true;
		this->puntajeObtenido = 0;
		this->multiplicadorPuntaje = 1;
		this->vidas = Pacman::VIDASDEFAULT;
		this->perseguido = true;
		this->sumaPuntosRival = false;
		this->siguienteDireccion = Pacman::DIRDERECHA;
		this->velocidad = Posicionable::VELOCIDAD_NORMAL;
	}

	Pacman(int x, int y):Posicionable(x,y){
		this->enMovimiento=true;
		this->vidas = Pacman::VIDASDEFAULT;
		this->puntajeObtenido = 0;
		this->multiplicadorPuntaje = 1;
		this->perseguido = true;
		this->sumaPuntosRival = false;
		this->siguienteDireccion = Pacman::DIRDERECHA;
		this->velocidad = Posicionable::VELOCIDAD_NORMAL;
	}



	~Pacman() {}



	void setDireccion(int d, MapaDeCeldas* m){
		int celdaX;
		int celdaY;
		switch(d){
			case Pacman::DIRDERECHA:
				celdaX = ((this->getPosX()+velocidad+this->getPasosPorCelda())/this->getPasosPorCelda());
				celdaY = (this->getPosY()/this->getPasosPorCelda());
				if(m->accederMapaTipo(celdaX,celdaY)>1 && this->getPosY()%this->getPasosPorCelda()==0)
				this->setValorDireccion(Pacman::DIRDERECHA);
				break;
			case Pacman::DIRABAJO:
				celdaX = ((this->getPosX())/this->getPasosPorCelda());
				celdaY = ((this->getPosY()+velocidad+this->getPasosPorCelda())/this->getPasosPorCelda());
				if(m->accederMapaTipo(celdaX,celdaY)>1 && this->getPosX()%this->getPasosPorCelda()==0)
				this->setValorDireccion(Pacman::DIRABAJO);
				break;
			case Pacman::DIRIZQUIERDA:
				celdaX = ((this->getPosX()-velocidad)/this->getPasosPorCelda());
				celdaY = (this->getPosY()/this->getPasosPorCelda());
				if(m->accederMapaTipo(celdaX,celdaY)>1 && this->getPosY()%this->getPasosPorCelda()==0)
				this->setValorDireccion(Pacman::DIRIZQUIERDA);
				break;
			case Pacman::DIRARRIBA:
				celdaX = ((this->getPosX())/this->getPasosPorCelda());
				celdaY = ((this->getPosY()-velocidad)/this->getPasosPorCelda());
				if(m->accederMapaTipo(celdaX,celdaY)>1 && this->getPosX()%this->getPasosPorCelda()==0)
				this->setValorDireccion(Pacman::DIRARRIBA);
				break;
			}
	}



	void corregirAlinealidad(){
		while(this->getPosX()%this->velocidad!=0){
			this->setPosicion(this->getPosX()+1,this->getPosY());
		}
		while(this->getPosY()%this->velocidad!=0){
			this->setPosicion(this->getPosX(),this->getPosY()+1);
		}
	}



//Este seria el equivalente a moverse(MapaDeCelda*)
	void vivir(MapaDeCeldas* m){
		int celdaX;
		int celdaY;
		int celdaY2;
		this->setDireccion(siguienteDireccion,m);
		if(enMovimiento){
			
		corregirAlinealidad();
		switch(this->getDireccion()){
			case 0:
				celdaX = ((this->getPosX()+this->getPasosPorCelda())/this->getPasosPorCelda());
				celdaY = (this->getPosY()/this->getPasosPorCelda());
				if(m->accederMapaTipo(celdaX,celdaY)>1)
					this->setPosicion(this->getPosX()+velocidad,this->getPosY());
				else{
					if(celdaX==m->getAncho()&&m->accederMapaTipo(this->getCeldaX(), this->getCeldaY())==m->CAMINOHORIZONTAL){
						this->setPosicion(0,this->getPosY());
					}
				}
				break;
			case 1:
				celdaX = ((this->getPosX())/this->getPasosPorCelda());
				celdaY = ((this->getPosY()+this->getPasosPorCelda())/this->getPasosPorCelda());
				celdaY2 = ((this->getPosY()+this->getPasosPorCelda()+velocidad)/this->getPasosPorCelda());
				if(m->accederMapaTipo(celdaX,celdaY)>1){
					this->setPosicion(this->getPosX(),this->getPosY()+velocidad);
				}
					if(celdaY2==m->getAlto() && m->accederMapaTipo(this->getCeldaX(), this->getCeldaY())==m->CAMINOVERTICAL){
						cout << "ENTRE!!!!!!!!!!!!!!!!!!!!!!" << endl;
						this->setPosicion(this->getPosX(),0);
					}
				
				break;
			case 2:
				celdaX = ((this->getPosX()-velocidad)/this->getPasosPorCelda());
				celdaY = (this->getPosY()/this->getPasosPorCelda());
				if(this->getPosX()-1>=0){
					if(m->accederMapaTipo(celdaX,celdaY)>1)
						this->setPosicion(this->getPosX()-velocidad,this->getPosY());
				}
				if(this->getPosX()==0 && m->accederMapaTipo(this->getCeldaX(), this->getCeldaY())==m->CAMINOHORIZONTAL){
					this->setPosicion((m->getAncho()-1)*this->getPasosPorCelda()-1,this->getPosY());
				}

				break;
			case 3:
				if(this->getPosY()-1>=0){
				celdaX = ((this->getPosX())/this->getPasosPorCelda());
				celdaY = ((this->getPosY()-velocidad)/this->getPasosPorCelda());
				if(m->accederMapaTipo(celdaX,celdaY)>1)
					this->setPosicion(this->getPosX(),this->getPosY()-velocidad);
				}
				if(this->getPosY()==0 && m->accederMapaTipo(this->getCeldaX(), this->getCeldaY())==m->CAMINOVERTICAL){
					this->setPosicion(this->getPosX(),(m->getAlto()-1)*this->getPasosPorCelda()-1);
					}
				break;
			}


		}
	}

 

	/*********SETTERS********/

	void setVelocidad(int v){
		this->velocidad = v;
	}

	void setSiguienteDireccion(int d, MapaDeCeldas* m){
		siguienteDireccion=d;
	}


	void setEnMovimiento(bool m){
		this->enMovimiento = m;
	}

	void setPuntajeObtenido(int puntaje) {
		this->puntajeObtenido = puntaje;
	}


	void setMultiplicadorPuntaje(int multiplicador) {
		this->multiplicadorPuntaje = multiplicador;
	}

	void setPerseguido(bool p){
		this->perseguido = p;
	}


	void setSumaPuntosRival(bool b){
		this->sumaPuntosRival = b;
	}


	void congelar() {
		this->enMovimiento = false;
	}

	/*******GETTERS*******/

	int getCeldaX(){
		if(this->getDireccion()==2){
			return (this->getPosX()+this->getPasosPorCelda())/this->getPasosPorCelda();
		}
		return this->getPosX()/this->getPasosPorCelda();
	}

	int getCeldaY(){
		if(this->getDireccion()==3){
			return (this->getPosY()+this->getPasosPorCelda()-velocidad)/this->getPasosPorCelda();
		}
		return this->getPosY()/this->getPasosPorCelda();
	}

	
	bool estaEnMovimiento(){
		return this->enMovimiento;
	}

	int getPuntajeObtenido() {
		return this->puntajeObtenido;
	}

	string getPuntajeObtenidoString(){
		char* a = new char();
		itoa(this->getPuntajeObtenido(),a,10);
		return (string)a;
	}

	int getMultiplicadorPuntaje() {
		return this->multiplicadorPuntaje;
	}

	int getVidas(){
		return this->vidas;
	}

	bool isPerseguido(){
		return this->perseguido;
	}

	bool isSumaPuntosRival(){
		return this->sumaPuntosRival;
	}

	void perderVida(){
		this->vidas--;
		this->setPosicion(this->getPosXinicial(),this->getPosYinicial());
	}



	/*
	 * Metodo que suma al puntaje obtenido el valor de puntajeASumar
	 */
	void aumentarPuntaje(int puntajeASumar) {
		this->puntajeObtenido += puntajeASumar*(this->multiplicadorPuntaje);
		
		// Agregado por Sonido
		Mix_Chunk *sonido;
		Mix_OpenAudio(44100, AUDIO_S16, 2, 4096);
		sonido = Mix_LoadWAV("Pacman_WAKAWAKA_WAV_00.03.wav");
		Mix_PlayChannel(-1, sonido, 0);
		// Fin Agregado por Sonido
	}


	/*
	 * Metodo que reestablece los valores por defecto del Pacman, como pueden ser la velocidad,
	 * el multiplicador de puntos o el indicador si es perseguido
	 */
	void reestablecer(){
		this->multiplicadorPuntaje = 1;
		this->perseguido = true;
		this->enMovimiento = true;
		this->sumaPuntosRival = false;
		this->velocidad = Posicionable::VELOCIDAD_NORMAL;
	}

};

#endif